import typing
from typing import Any
from typing import List
from typing import Union
from typing import Mapping
from typing import Callable
from typing import Optional
from typing import overload
from datetime import datetime

import six

from .enums import ResourceType
from .permissions import Permissions

Text = str

RawInfo = Mapping[Text, Mapping[Text, object]]
ToDatetime = Callable[[int], datetime]
T = typing.TypeVar("T")

@six.python_2_unicode_compatible
class Info:
    __slots__ = ["raw", "_to_datetime", "namespaces"]

    def __init__(self, raw_info: RawInfo, to_datetime: ToDatetime = ...) -> None: ...
    def __str__(self) -> str: ...
    def __repr__(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    @overload
    def get(self, namespace: Text, key: Text) -> Any: ...
    @overload
    def get(self, namespace: Text, key: Text, default: T) -> Union[Any, T]: ...
    def get(
        self, namespace: Text, key: Text, default: Optional[Any] = ...
    ) -> Optional[Any]: ...
    def is_writeable(self, namespace: Text, key: Text) -> bool: ...
    def has_namespace(self, namespace: Text) -> bool: ...
    def copy(self, to_datetime: Optional[ToDatetime] = ...) -> Info: ...
    def make_path(self, dir_path: Text) -> Text: ...
    @property
    def name(self) -> Text: ...
    @property
    def suffix(self) -> Text: ...
    @property
    def suffixes(self) -> List[Text]: ...
    @property
    def stem(self) -> Text: ...
    @property
    def is_dir(self) -> bool: ...
    @property
    def is_file(self) -> bool: ...
    @property
    def is_link(self) -> bool: ...
    @property
    def type(self) -> ResourceType: ...
    @property
    def accessed(self) -> Optional[datetime]: ...
    @property
    def modified(self) -> Optional[datetime]: ...
    @property
    def created(self) -> Optional[datetime]: ...
    @property
    def metadata_changed(self) -> Optional[datetime]: ...
    @property
    def permissions(self) -> Optional[Permissions]: ...
    @property
    def size(self) -> int: ...
    @property
    def user(self) -> Optional[Text]: ...
    @property
    def uid(self) -> Optional[int]: ...
    @property
    def group(self) -> Optional[Text]: ...
    @property
    def gid(self) -> Optional[int]: ...
    @property
    def target(self) -> Optional[Text]: ...
